﻿using System;
using System.Collections.Generic;
using StockholmsStad.Data.Interfaces;
using StockholmsStad.Utilities.Enums;
using StockholmsStad.Utilities.Exceptions;
using StockholmsStad.Runtime.Serialization.DataContract;
using StockholmsStad.Runtime.Serialization.DataContract.Enums;

namespace StockholmsStad.Business
{
    /// <summary>
    /// Hanterar affärslogik för bokningar
    /// </summary>
    public class MinisterBusiness : BusinessBase
    {
        private const bool useTransaction = true;

        /// <summary>
        /// Skapar business-objektet
        /// </summary>
        /// <param name="user"></param>
        public MinisterBusiness(User user)
            : base(user)
        {
        }

        /// <summary>
        /// Kontrollerar om bokningskoden är giltig för någon förättare
        /// </summary>
        /// <param name="ministerCode">Förrättarkoden.</param>
        public bool IsBookingCodeValid(string ministerCode)
        {
            IMinisterAgent ministerAgent = AgentFactory.GetMinisterAgent();
            using (IDataContext context = GetDataContext(false))
            {
                return ministerAgent.GetMinisterIdByMinisterCode(context, ministerCode) != null;
            }
        }

        ///<summary>
        /// Lägger till en ny förrättare
        ///</summary>
        ///<param name="minister"></param>
        ///<returns>Det erhållna id-numret på den tillagda förrättaren.</returns>
        public int AddMinister(Minister minister)
        {
            if (CurrentUser.Role == UserRole.ReadOnly || CurrentUser.Role == UserRole.Customer)
                throw new StockholmStadSystemException(SystemErrorCode.AccessDenied);

            IMinisterAgent ministerAgent = AgentFactory.GetMinisterAgent();
            using (IDataContext context = GetDataContext(useTransaction))
            {
                int id = ministerAgent.AddMinister(context, minister);
                context.TransactionComplete();
                return id;
            }
        }

        ///<summary>
        /// Uppdatera förättare
        ///</summary>
        ///<param name="minister">Förrättaren (<see cref="Minister"/>) som ska läggas till.</param>
        public void UpdateMinister(Minister minister)
        {
            if (CurrentUser.Role == UserRole.ReadOnly || CurrentUser.Role == UserRole.Customer)
                throw new StockholmStadSystemException(SystemErrorCode.AccessDenied);

            IMinisterAgent ministerAgent = AgentFactory.GetMinisterAgent();
            using (IDataContext context = GetDataContext(useTransaction))
            {
                ministerAgent.UpdateMinister(context, minister.MinisterId.Value, minister);
                context.TransactionComplete();
            }
        }

        ///<summary>
        /// Ta bort en förrättare
        ///</summary>
        ///<param name="ministerId">Id-numret på den förrättare som ska tas bort.</param>
        public void RemoveMinister(int ministerId)
        {
            if (CurrentUser.Role == UserRole.ReadOnly || CurrentUser.Role == UserRole.Customer)
                throw new StockholmStadSystemException(SystemErrorCode.AccessDenied);

            IMinisterAgent ministerAgent = AgentFactory.GetMinisterAgent();
            using (IDataContext context = GetDataContext(useTransaction))
            {
                ministerAgent.RemoveMinister(context, ministerId);
                context.TransactionComplete();
            }
        }

        ///<summary>
        ///</summary>
        ///<param name="ministerId"></param>
        ///<returns></returns>
        public Minister GetMinister(int ministerId)
        {
            IMinisterAgent ministerAgent = AgentFactory.GetMinisterAgent();
            using (IDataContext context = GetDataContext(false))
            {
                return ministerAgent.GetMinister(context, ministerId);
            }
        }

        ///<summary>
        /// Hämtar alla förrättare
        ///</summary>
        /// <returns>En lista av förrättare (<see cref="Minister"/>).</returns>
        public List<Minister> GetMinisters()
        {
            IMinisterAgent ministerAgent = AgentFactory.GetMinisterAgent();
            using (IDataContext context = GetDataContext(false))
            {
                return ministerAgent.GetMinisters(context);
            }
        }

        /// <summary>
        /// Hämtar alla förrättare som är verksamma inom angiven period
        /// </summary>
        /// <param name="date">Det datum vars förrättningsperiod måste innehålla.</param>
        /// <returns>En lista av förrättare (<see cref="Minister"/>).</returns>
        public List<Minister> GetMinisters(DateTime date)
        {
            var ministerAgent = AgentFactory.GetMinisterAgent();
            using (var context = GetDataContext(false))
            {
                return ministerAgent.GetMinisters(context, date);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="partOfName"></param>
        /// <param name="assignmentStartDate"></param>
        /// <param name="assignmentEndDate"></param>
        /// <param name="isActive"></param>
        /// <returns></returns>
        public List<Minister> GetMinisters(string partOfName, DateTime? assignmentStartDate,
                                    DateTime? assignmentEndDate, bool isActive)
        {
            var ministerAgent = AgentFactory.GetMinisterAgent();
            using (var context = GetDataContext(false))
            {
                return ministerAgent.GetMinisters(context, partOfName, assignmentStartDate, assignmentEndDate,
                                                  isActive);
            }
        }

        /// <summary>
        /// Hämtar tidsblock för en förrättare
        /// </summary>
        /// <param name="ministerId">Id-numret på den förrättare som tidsblock ska hämtas för. </param>
        /// <returns>En lista med tidsblock</returns>
        public List<MinisterTimeBlock> GetTimeBlockForMinister(int ministerId)
        {
            List<MinisterTimeBlock> list;

            using (var context = GetDataContext(false))
            {
                var agent = AgentFactory.GetMinisterAgent();
                list = agent.GetTimeBlocksForMinister(context, ministerId);
            }

            return list;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ministerId"></param>
        /// <param name="date"></param>
        /// <returns></returns>
        public bool HasMinisterAnyServices(int ministerId, DateTime date)
        {
            using (var context = GetDataContext(false))
            {
                var agent = AgentFactory.GetMinisterAgent();
                return agent.HasMinisterAnyServices(context, ministerId, date);
            }            
        }
    }
}